home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Libraries / VideoToolbox 94.11.17 / VideoToolboxSources / CreateTrialSnds.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-05  |  6.0 KB  |  171 lines  |  [TEXT/KAHL]

  1. /* CreateTrialSnds.c
  2. Create snd resources for 2afc testing: a "beep" for each presentation,
  3. rightSnd, wrongSnd, and abortSnd for feedback, and a "purr" that I use between 
  4. the presentation and response to indicate to the user that the computer 
  5. is waiting for a response. You can play these sounds by using Apple's SndPlay(), 
  6. or my SndPlay1(), which is in the VideoToolbox. Note that these are proper
  7. resources and are interchangeable with other snd resources, which you can
  8. retrieve by calling GetNamedResource('snd ',"\pSimple Beep"), for example.
  9. You could also use the sound recording capabilities of your Mac to record
  10. spoken words like "right" and "wrong", accessible in the same way.
  11.  
  12. It's ok to call this routine repeatedly, after the first time it has no effect
  13. since it's smart enough to notice that the sounds have already been created.
  14.  
  15. Unlike other routines in VideoToolboxSources, you will probably not use this
  16. routine unaltered. Instead you'll probably modify the code to produce
  17. sounds that suit your own purposes.
  18.  
  19. Note that the sound handles are published as globals. I don't like using globals,
  20. because they make information flow impossible to work out, but in this case
  21. all alternatives seem unreasonably cumbersome.
  22.  
  23. In updating my software from the Sound Driver to the Sound Manager I was
  24. disappointed to discover that the squareWaveSynth supplied by the Sound
  25. Manager doesn't sound at all like the square wave synthesizer of the
  26. Sound Driver. It seems to interpolate, resulting in smoother waveforms that
  27. are inaudible at low frequencies, even if you set the timbre parameter to 255.
  28. E.g. my "purr" is a 22 Hz square wave of which one only hears the clicks at
  29. the transitions, and is thus inaudible after smoothing. Fortunately one can 
  30. recreate the old square wave synthesizer by using the sampledSynth with 
  31. no interpolation, playing from a square wave table, which can be included in the
  32. snd resource. 
  33.  
  34. Note that the beep, which uses the squareWaveSynth, continues playing even while 
  35. interrupts are suspended, e.g. by calling SetPriority(7), while the sounds
  36. produced by the sampledSynth pause while interrupts are suspended. This
  37. implies that the sound chip must implement the squareWaveSynth all by itself.
  38. However, the beep never ends as long as the interrupts remain suspended.
  39. The practical consequence of all this is that you can use "beep" to play
  40. sounds simultaneously with stimuli that (for maximum performance) require
  41. suspension of interrupts.
  42. HISTORY:
  43. 4/1/92    dgp extracted it from DoATrial.c
  44. */
  45. #include "VideoToolbox.h"
  46. #include <Sound.h>
  47.  
  48. Handle beep=NULL,rightSnd=NULL,wrongSnd=NULL,abortSnd=NULL,purr=NULL;
  49.  
  50. typedef struct {            // A 'snd ' resource of type 1. See Inside Mac VI:22-19.
  51.     short format;            // must equal 1
  52.     short numberOfSynths;    // 1 in this structure
  53.     short synth;
  54.     long synthInitOption;
  55.     short numberOfCommands;
  56.     SndCommand commands[];
  57. } Snd1Resource;
  58.  
  59. void CreateTrialSnds(void)
  60. {
  61.     Snd1Resource *s;
  62.     SoundHeader **squareWaveTable;
  63.     
  64.     if(beep!=NULL)return;
  65.     
  66.     squareWaveTable=(SoundHeader **)NewHandle(sizeof(SoundHeader)+8);
  67.     if(squareWaveTable==NULL)goto error;
  68.     (*squareWaveTable)->samplePtr=NULL;
  69.     (*squareWaveTable)->length=8;
  70.     (*squareWaveTable)->sampleRate=880*0x10000;    // 880 Hz
  71.     (*squareWaveTable)->loopStart=0;
  72.     (*squareWaveTable)->loopEnd=8;
  73.     (*squareWaveTable)->encode=stdSH;
  74.     (*squareWaveTable)->baseFrequency=57;        // 440 Hz
  75.     (*squareWaveTable)->sampleArea[0]=0;
  76.     (*squareWaveTable)->sampleArea[1]=255;
  77.     (*squareWaveTable)->sampleArea[2]=0;
  78.     (*squareWaveTable)->sampleArea[3]=255;
  79.     (*squareWaveTable)->sampleArea[4]=0;
  80.     (*squareWaveTable)->sampleArea[5]=255;
  81.     (*squareWaveTable)->sampleArea[6]=0;
  82.     (*squareWaveTable)->sampleArea[7]=255;
  83.  
  84.     purr=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  85.     if(purr==NULL)goto error;
  86.     s=(Snd1Resource *)*purr;
  87.     s->format=1;
  88.     s->numberOfSynths=1;
  89.     s->synth=sampledSynth;
  90.     s->synthInitOption=initNoInterp;
  91.     s->numberOfCommands=4;
  92.     s->commands[0].cmd=soundCmd+dataOffsetFlag;
  93.     s->commands[0].param1=0;
  94.     s->commands[0].param2=GetHandleSize(purr);
  95.     s->commands[1].cmd=ampCmd;
  96.     s->commands[1].param1=70;
  97.     s->commands[1].param2=0;
  98.     s->commands[2].cmd=freqCmd;
  99.     s->commands[2].param1=0;
  100.     s->commands[2].param2=1;        // 17 Hz
  101.     s->commands[3].cmd=nullCmd;
  102.     s->commands[3].param1=0;
  103.     s->commands[3].param2=0;
  104.     HLock((Handle)squareWaveTable);
  105.     HandAndHand((Handle)squareWaveTable,purr);    // append squareWaveTable
  106.     DisposeHandle((Handle)squareWaveTable);
  107.     
  108.     abortSnd=purr;
  109.     if(HandToHand(&abortSnd))goto error;
  110.     s=(Snd1Resource *)*abortSnd;
  111.     s->commands[1].cmd=ampCmd;
  112.     s->commands[1].param1=80;
  113.     s->commands[1].param2=0;
  114.     s->commands[2].cmd=freqDurationCmd;
  115.     s->commands[2].param1=2400;
  116.     s->commands[2].param2=69-5*12;    // 27.5 Hz
  117.     s->commands[3].cmd=quietCmd;
  118.     s->commands[3].param1=0;
  119.     s->commands[3].param2=0;
  120.  
  121.     wrongSnd=abortSnd;
  122.     if(HandToHand(&wrongSnd))goto error;
  123.     s=(Snd1Resource *)*wrongSnd;
  124.     s->synthInitOption=0;
  125.     s->commands[1].cmd=ampCmd;
  126.     s->commands[1].param1=100;
  127.     s->commands[1].param2=0;
  128.     s->commands[2].cmd=freqDurationCmd;
  129.     s->commands[2].param1=1200;
  130.     s->commands[2].param2=69-12;    // 880/2 Hz
  131.  
  132.     beep=NewHandle(sizeof(Snd1Resource)+4*sizeof(SndCommand));
  133.     if(beep==NULL)goto error;
  134.     s=(Snd1Resource *)*beep;
  135.     s->format=1;
  136.     s->numberOfSynths=1;
  137.     s->synth=squareWaveSynth;
  138.     s->synthInitOption=0;
  139.     s->numberOfCommands=4;
  140.     s->commands[0].cmd=timbreCmd;
  141.     s->commands[0].param1=20;
  142.     s->commands[0].param2=0;
  143.     s->commands[1].cmd=ampCmd;
  144.     s->commands[1].param1=100;
  145.     s->commands[1].param2=0;
  146.     s->commands[2].cmd=freqDurationCmd;
  147.     s->commands[2].param1=4000;
  148.     s->commands[2].param2=69;        // 880 Hz
  149.     s->commands[3].cmd=quietCmd;
  150.     s->commands[3].param1=0;
  151.     s->commands[3].param2=0;
  152.     
  153.     rightSnd=beep;
  154.     if(HandToHand(&rightSnd))goto error;
  155.     s=(Snd1Resource *)*rightSnd;
  156.     s->commands[0].cmd=timbreCmd;
  157.     s->commands[0].param1=0;
  158.     s->commands[0].param2=0;
  159.     s->commands[1].cmd=ampCmd;
  160.     s->commands[1].param1=100;
  161.     s->commands[1].param2=0;
  162.     s->commands[2].cmd=freqDurationCmd;
  163.     s->commands[2].param1=100;
  164.     s->commands[2].param2=69+12;    // 2*880 Hz
  165.  
  166.     return;
  167.     
  168.     error:
  169.     PrintfExit("Not enough memory. %s line %d\n",__FILE__,__LINE__);
  170. }
  171.